/** \file    timing.h
  * \brief   Gives a means for timing a program with details for routines call-tree.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/mswin/timing.h,v 1.7 2005/05/24 11:15:27 cscom1r4 Exp $
  */

#ifndef _timing_h_
#define _timing_h_

#include <string>
#include <iostream>

namespace mswin { class timing_tree; }

namespace xml { 
	class stream;
	stream & operator || (stream & s, mswin::timing_tree & t); 
}

namespace mswin {

class timing_tree {
public:
	timing_tree();
	timing_tree(const timing_tree & rhs);
	~timing_tree();
	timing_tree & operator = (const timing_tree & rhs);
	///appends all nodes & times of rhs into this
	timing_tree & operator += (const timing_tree & rhs);
	void clear();
	friend std::ostream & operator << (std::ostream & out, const timing_tree & t); 
	bool in_use() const { return _root != _current; }
public:
	struct node;
private:
	//allows tree modification from const methods
	mutable node * _root;
	mutable node * _current; ///<last timing was initiated for this node
	friend class timing_mark;
	friend xml::stream & xml::operator || (xml::stream & s, timing_tree & t); 
};

///ctor enters in tree node, dtor updates current node and its immediate parent
class timing_mark
{
public:
	timing_mark(const timing_tree & tree, const std::string & node_name);
	///do nothing if pointer on tree is zero
	timing_mark(const timing_tree * tree, const std::string & node_name);
	timing_mark(timing_mark & snatch);
	~timing_mark();
	double seconds() const; ///< returns time passed since object creation
	void finish(); ///< the tree is updated with the time passed, and the object becomes inactive
private:
	void init(const std::string & node_name);
	void operator = (timing_mark &); ///<prohibit
private:
	const timing_tree & _tree;
	timing_tree::node * _parent;
};

} //namespace mswin

#endif //_timing_h_
